package com.kjhxtc.restfulrunner;

import cn.hutool.core.util.StrUtil;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.kjhxtc.restfulrunner.Runner.KEEP_ALIVE;

/**
 * @author 杜神
 * @version 1.0
 * @since 2022/3/16 10:58
 */
public class Task {

    private final String method;
    private final String url;
    private final String version;
    private final String data;
    private final Map<String, Object> headers = new HashMap<>();
    private final RestfulClientManager clientManager;
    private final ResultCollector resultCollector;

    /**
     * POST http://127.0.0.1:5001/api/info
     * Content-Type:application/json
     * secretKey:asd
     * <p>
     * {}
     *
     * @param command
     */
    public Task(String command,RestfulClientManager clientManager,ResultCollector resultCollector) {
        this.clientManager=clientManager;
        this.resultCollector=resultCollector;
        command = StrUtil.trim(command);
        String[] groups = command.split("\n");
        if (groups.length == 0) {
            throw new IllegalArgumentException("请求指令为空");
        }
        Pattern pattern = Pattern.compile("^\\s*([^\\s]+)\\s+(.*)\\s?(.*)\\s*$");
        Matcher matcher = pattern.matcher(groups[0]);
        if (!matcher.matches()) {
            throw new IllegalArgumentException("请求指令格式不正确");
        }
        this.method=matcher.group(1).toUpperCase(Locale.ROOT);
        this.url = matcher.group(2);
        this.version=matcher.group(3);
        int flag=-1;
        for (int i = 1; i < groups.length; i++) {
            if (StrUtil.isBlank(groups[i])){
                flag=i;
                break;
            }
            Pattern pattern2 = Pattern.compile("^\\s*(.*):(.*)\\s*$");
            Matcher matcher2 = pattern2.matcher(groups[i]);
            if (!matcher2.matches()){
                throw new IllegalArgumentException("header格式不正确\n"+groups[i]);
            }
            headers.put(StrUtil.trim(matcher2.group(1)),StrUtil.trim(matcher2.group(2)));
        }
        if (flag!=-1){
            StringBuilder sb = new StringBuilder();
            for (int i = flag; i < groups.length; i++) {
                sb.append(groups[i]);
            }
            data=sb.toString();
        }else {
            data=null;
        }
    }

    public void execute() {
        HttpUriRequest request;
        RestfulClient restfulClient = clientManager.get();
        CloseableHttpClient httpClient = restfulClient.getHttpClient();
        if ("POST".equals(this.method)){
            HttpPost httpPost = new HttpPost(this.url);
            try {
                httpPost.setEntity(new StringEntity(this.data));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            request = httpPost;
        }else if ("GET".equals(this.method)){
            request = new HttpGet(this.url);
        }else if ("PUT".equals(this.method)){
            HttpPut httpPut = new HttpPut(this.url);
            try {
                httpPut.setEntity(new StringEntity(this.data));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            request = httpPut;
        }else if ("DELETE".equals(this.method)){
            request = new HttpDelete(this.url);
        }else {
            throw new IllegalArgumentException("http方法不支持:"+this.method);
        }
        headers.keySet().forEach(key -> request.addHeader(key, headers.get(key) + ""));
        try {
            long beginTime = System.currentTimeMillis();
            RestfulClient.traceRequest(request);
            CloseableHttpResponse response = httpClient.execute(request);
            RestfulClient.traceResponse(response);
            if(KEEP_ALIVE && null != response.getEntity()){
                EntityUtils.consume(response.getEntity());
            }
            Result result = new Result();
            result.setCost(System.currentTimeMillis()-beginTime);
            result.setStatusCode(response.getStatusLine().getStatusCode()+"");
            result.setSuccess(response.getStatusLine().getStatusCode()==200);
            result.setErrMsg(response.getStatusLine().toString());
            resultCollector.add(result);
            response.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
